import 'dart:async';
import 'dart:convert';
import 'package:flutter/services.dart';

import 'mini_app_info.dart';

/**
 *
 * @Author qiujun
 * @Date 2022/9/23 3:43 下午
 * @Description flutter 端 桥接到 小程序端的 插件
 *
 **/

class FlutterUniappPlugin {
  /// 单例模式设计
  factory FlutterUniappPlugin() => _getInstance()!;

  static FlutterUniappPlugin? _instance;

  static FlutterUniappPlugin? _getInstance() {
    if (_instance == null) {
      _instance = FlutterUniappPlugin._internal();
    }

    return _instance;
  }

  static const MethodChannel _channel =
      const MethodChannel('flutter_uniapp_plugin');

  FlutterUniappPlugin._internal() {
    _channel.setMethodCallHandler(receiveMessageFromMiniAPP);
  }

  /// 获取原生APP 的版本号信息
  static Future<String?> get platformVersion async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static Future<String?> get testPlugin async {
    final String? iOSStr = await _channel.invokeMethod('testPlugin');
    return iOSStr;
  }

  /// method_name openMiniAPP
  /// description 打开指定小程序
  /// @param
  /// [miniAppInfo] 小程序基本信息 (包括唯一id,
  ///      miniAPPId,
  ///       miniAPPVersion,
  ///       miniMPSDKVersion,
  ///       homePage,
  ///       jumpPage
  ///       )等
  ///    详细请看 [ MiniAppInfo ] 类 说明
  ///
  /// [miniAppInfo.jumpPage], 小程序的页面路径 (打开指定页面使用)  ,如果不传,则默认打开小程序的首页
  /// [params] Flutter 端 传递给小程序端的业务参数 JSON 格式,{key : value}
  ///
  /// @return
  /// Future<Map<String, dynamic>?>
  ///  接口返回的参数协议
  ///   [code] 接口状态码,
  ///      0 代表成功, 其他状态码都是失败
  ///      100 代表当前小程序指定运行环境SDK 版本和 宿主APP SDK 不兼容
  ///        (一般是 指定小程序运行SDK 版本环境 高于了 本地基座SDK,需要APP 原生端更新 小程序SDK 环境才可以运行)
  ///        [解决方案]  1.将小程序运行环境SDK版本 降低 到和APP 基座SDK版本 一致,或者比基座 版本低
  ///                  2.更新原生APP 基座SDK版本 (需要原生发版)
  ///         <<小程序发布注意>> 一般只发布和基座SDK版本一致的小程序,或者比基座版本低的
  ///      101  代表APP 本地不存在该小程序. 需要远程加载小程序.
  ///             可能是远程加载错误(比如下载异常,中途退出,网络中断等)
  ///             也可能远程下载成功了,本地运行时出错
  ///      102 代表APP 本地存在改小程序,但是本地运行加载失败....
  ///      103 小程序打开成功了,但是没有打开到指定的页面,只停留在小程序首页
  ///           (可能原因: 小程序的指定路径路由不正确,亦或者打开指定页面的业务参数不正确)
  ///     -1 代表失败, 未知错误(代码debug 排查一下咯)
  ///
  ///   [message] 返回信息
  ///
  ///   [params] 小程序端返回给 Flutter 端的业务参数
  ///
  ///      打开成功,返回参数案例:
  ///    Map<String, dynamic> result = {
  ///       'code': 0,
  ///       'message': '打开小程序成功',
  ///      'params': {
  ///         'key1': 'value1',
  ///         'key2': 'value2',
  ///        'key3': 'value3',
  ///         ///......
  ///       }
  ///     };
  ///
  ///

  static Future<Map<String, dynamic>?> openMiniAPP(
    MiniAppInfo miniAppInfo, {
    Map<String, dynamic>? params,
  }) async {
    ///  小程序Id 不可能太短,非法id
    assert(miniAppInfo.miniAPPId.length > 5, '小程序Id 太短,非法Id');

    /// 组装 打开小程序的所有参数
    Map<String, dynamic>? allParams = {
      'miniAPPId': miniAppInfo.miniAPPId,
      'miniAPPVersion': miniAppInfo.miniAPPVersion,
      'miniMPSDKVersion': miniAppInfo.miniMPSDKVersion,
      'miniAPPSourceURL':miniAppInfo.miniAPPSourceURL,
      'homePage': miniAppInfo.homePage,
    };

    ///拼接 小程序的页面路径
    if (miniAppInfo.jumpPage != null) {
      allParams['jumpPage'] = miniAppInfo.jumpPage;
    }

    ///  拼接其他业务参数
    if (params != null) {
      allParams['extraData'] = params;
    }

    final dynamic result =
        await _channel.invokeMethod('openMiniAPP', allParams);

    Map<String, dynamic>? resultMap = json.decode(json.encode(result));

    return resultMap;
  }

  /// method_name getUniMPSDKVersion
  /// description  获取原生基座中,小程序SDK版本信息  (方便进行版本兼容性判断)
  /// @param
  ///
  /// @return
  ///

  static Future<String?> getUniMPSDKVersion() async {
    String version = await _channel.invokeMethod('getUniMPSDKVersion');
    return version;
  }

  /// method_name canOpenMiniAPP
  /// description 是否可以打开指定小程序
  ///   @param
  ///   [miniAPPId],  1. 小程序唯一ID, 原生内部需要判断是否存在该小程序的运行包
  ///   [miniAPPVersion] 2. 小程序本身的版本号
  ///   [miniMPSDKVersion] 3.小程序运行的最低SDK版本, 原生内部需要判断,指定的小程序和当前原生基座小程序SDK版本 是否兼容
  ///
  /// @return  Future<bool>
  ///          true 可以打开
  ///          false 不可以打开
  ///

  Future<bool> canOpenMiniAPP(
    String miniAPPId, {
    String? miniAPPVersion,
    String? miniMPSDKVersion,
  }) async {
    ///  小程序Id 不可能太短,非法id
    assert(miniAPPId.length > 5, '小程序Id 太短,非法Id');

    /// 组装 所有参数
    Map<String, dynamic>? allParams = {
      'miniAPPId': miniAPPId,
      'miniAPPVersion': miniAPPVersion ?? '',
      'miniMPSDKVersion': miniMPSDKVersion ?? '',
    };
    bool result = await _channel.invokeMethod('canOpenMiniAPP', allParams);
    return result;
  }

  /// method_name sentMessageToMiniAPP
  /// description 发送消息到 小程序端  (异步发送)
  /// @param
  /// [miniAPPId] 指定的小程序ID
  /// [map] 发送的消息内容 (自定义json 结构),比如用户的token 登录信息,相关的业务数据
  ///
  /// @return
  /// Future<Map<String, dynamic>?>
  ///  消息是否发送成功
  ///
  static Future<Map<String, dynamic>?> sentMessageToMiniAPP(
      String miniAPPId, Map<String, dynamic> map) async {
    ///  小程序Id 不可能太短,非法id
    assert(miniAPPId.length > 5);

    Map<String, dynamic>? result =
        await _channel.invokeMethod('sentMessageToMiniAPP', map);
    return result;
  }

  /// method_name receiveMessageFromMiniAPP
  /// description 接收 小程序 发过来的消息
  /// @param
  /// [call.method]  小程序端 调用Flutter 端的 函数名
  /// [call.arguments]   小程序 端发送过来的 参数
  /// @return
  /// Future<Null>

  Future<Null> receiveMessageFromMiniAPP(MethodCall call) async {
    /// 根据 函数名 再次分发到各个函数实现中去 执行.
    switch (call.method) {
      case 'testMethod':

        ///  testMethod();
        break;

      case 'testMethod1':

        ///  testMethod();
        break;

      case 'testMethod2':

        ///  testMethod();
        break;

      default:

      ///  testMethod();

    }
  }
}
